/**
	* \file		Mouse.cpp
  *         Simple wrapper around the XINPUT_STATE and XINPUT_CAPABILITIES
  *         structures, providing utility functions such as IsButtonPressed
	*/


//= I N C L U D E S ===========================================================
#include "Mouse.h"
#include "Gamepad.h"
#include "InputManager.h"
#include "DebugLogger.h"


//= D E F I N E S =============================================================
//#define STICK_DEADZONE              0.38f

//= G L O B A L = V A R S =====================================================


//= F U N C T I O N S =================================================



//------------------------------------------------------
//	Constructor
//------------------------------------------------------
CMouse::CMouse( void ) : CInputDevice()
{
}

//------------------------------------------------------
//	Create
//------------------------------------------------------
BOOL CMouse::Create(  DWORD gpIndex, 
                        CInputManager *inputManager )
{
  if( gpIndex > 3 || !inputManager )
    return FALSE;

  if( !CInputDevice::Create( gpIndex, inputManager ) )
    return FALSE;
/*
	switch( m_portIndex )
	{
	default:
//			assert( 0 && "Invalid gamepad port number!" );
		// fallthrough

		// *** 0 *** //
	case 0:
		m_portName          = XDEVICE_PORT0;
		m_portMask          = XDEVICE_PORT0_MASK;
		break;

		// *** 1 *** //
	case 1:
		m_portName          = XDEVICE_PORT1;
		m_portMask          = XDEVICE_PORT1_MASK;
		break;

		// *** 2 *** //
	case 2:
		m_portName          = XDEVICE_PORT2;
		m_portMask          = XDEVICE_PORT2_MASK;
		break;

		// *** 3 *** //
	case 3:
		m_portName          = XDEVICE_PORT3;
		m_portMask          = XDEVICE_PORT3_MASK;
		break;
	}
*/
  return TRUE;
}

//------------------------------------------------------
//	PollDevice
//------------------------------------------------------
void CMouse::PollDevice( void )
{
  m_inputManager->AttachRemoveDevices();

  if( m_deviceHandle )
    XInputGetState( m_deviceHandle, &m_state );
}

//------------------------------------------------------
//	WaitForAnyButton
//------------------------------------------------------
void CMouse::WaitForAnyButton( void ) 
{
  if( !m_deviceHandle )
  {
    PRINTMSG(( T_ERROR, "WaitForAnyButton called on invalid mouse!" ));
    return;
  }

  do
  {
    PollDevice();
  } while( !IsAnyButtonPressed() );
}

//------------------------------------------------------
//	WaitForNoButton
//------------------------------------------------------
void CMouse::WaitForNoButton( void ) 
{
  if( !m_deviceHandle )
  {
    PRINTMSG(( T_ERROR, "WaitForNoButton called on invalid mouse!" ));
    return;
  }

	do
	{
		PollDevice();
  } while( IsAnyButtonPressed() );
}

//------------------------------------------------------
//	WaitForAnyInput
//------------------------------------------------------
void CMouse::WaitForAnyInput( void ) 
{
  if( !m_deviceHandle )
  {
    PRINTMSG(( T_ERROR, "WaitForAnyInput called on invalid mouse!" ));
    return;
  }

	do
	{
		PollDevice();
  } while( !GetInputState() );
}

//------------------------------------------------------
//	WaitForNoInput
//------------------------------------------------------
void CMouse::WaitForNoInput( void ) 
{
  if( !m_deviceHandle )
  {
    PRINTMSG(( T_ERROR, "WaitForNoInput called on invalid mouse!" ));
    return;
  }

	do
	{
		PollDevice();
  } while( GetInputState() );
}


//------------------------------------------------------
//	GetInputState
//------------------------------------------------------
UINT32 CMouse::GetInputState( void ) const
{
  if( !IsConnected() )
    return 0;

  const XINPUT_MOUSE &m = m_state.DebugMouse;
	UINT32 curState;

	curState = 0;
	curState |= ( ( m.bButtons & XINPUT_DEBUG_MOUSE_LEFT_BUTTON ) != 0 ) ? GP_A : 0;
	curState |= ( ( m.bButtons & XINPUT_DEBUG_MOUSE_RIGHT_BUTTON ) != 0 ) ? GP_B : 0;
	curState |= ( ( m.bButtons & XINPUT_DEBUG_MOUSE_MIDDLE_BUTTON ) != 0 ) ?  GP_X : 0;
	curState |= ( ( m.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON1 ) != 0 ) ?  GP_LEFT_TRIGGER : 0;
	curState |= ( ( m.bButtons & XINPUT_DEBUG_MOUSE_XBUTTON2 ) != 0 ) ?  GP_RIGHT_TRIGGER : 0;


  #define DELTA_AS_DIGITAL_VAL    ( char )( 5 )

	curState |= ( m.cMickeysY >=  DELTA_AS_DIGITAL_VAL ) ? GP_LA_DOWN : 0;
	curState |= ( m.cMickeysX <= -DELTA_AS_DIGITAL_VAL ) ? GP_LA_LEFT : 0;
	curState |= ( m.cMickeysY <= -DELTA_AS_DIGITAL_VAL ) ? GP_LA_UP : 0;
	curState |= ( m.cMickeysX >=  DELTA_AS_DIGITAL_VAL ) ? GP_LA_RIGHT : 0;

  return( curState );
}

//------------------------------------------------------
//	IsAnyButtonPressed
//------------------------------------------------------
BOOL CMouse::IsAnyButtonPressed( void ) const
{
	UINT32 state = GetInputState();

	  // Only Buttons
	state &= ( GP_A | GP_B | GP_X | GP_LEFT_TRIGGER | GP_RIGHT_TRIGGER );

	return( state != 0 );
}

//------------------------------------------------------
//	IsButtonPressed
//------------------------------------------------------
BOOL CMouse::IsButtonPressed( UINT32 buttonID ) const
{
  return ( (GetInputState() & buttonID) == buttonID );
}

//------------------------------------------------------
//	IsOnlyButtonPressed
//------------------------------------------------------
BOOL CMouse::IsOnlyButtonPressed( UINT32 buttonID ) const
{
  return ( GetInputState() == buttonID );
}

//------------------------------------------------------
//	IsOneOfButtonsPressed
//------------------------------------------------------
BOOL CMouse::IsOneOfButtonsPressed( UINT32 buttonID ) const
{
  return ( GetInputState() & buttonID );
}


//------------------------------------------------------
//	GetMouseDeviceState
//------------------------------------------------------
const XINPUT_MOUSE *CMouse::GetMouseDeviceState( void ) const 
{
  if( IsConnected() )
	  return &m_state.DebugMouse;

  return NULL;
}


//------------------------------------------------------
//	AttachRemoveDevices
//------------------------------------------------------
void CMouse::AttachRemoveDevices( void ) 
{
		// Attach/Remove mice
	AttachRemoveMouseDevice();
}

//------------------------------------------------------
//	AttachRemoveMouseDevice
//------------------------------------------------------
void CMouse::AttachRemoveMouseDevice( void )
{
	if( !(m_inputManager->GetMouseDeviceBitmap() & m_portMask ) && m_deviceHandle )
	{
			// Detach
		XInputClose( m_deviceHandle );
		m_deviceHandle = NULL;
		m_state.dwPacketNumber = 0;
	}

	if(	(m_inputManager->GetMouseDeviceBitmap() & m_portMask ) && !m_deviceHandle )
	{
			// Attach
		m_deviceHandle = XInputOpen( XDEVICE_TYPE_DEBUG_MOUSE,
																							            m_portName,				
																							            XDEVICE_NO_SLOT,			// Mouse, so no slot
																							            NULL );								// No special polling params
    assert( m_deviceHandle );
//    XInputGetCapabilities( m_deviceHandle, &m_caps );
	}
}




